#include <cmath>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <ctime>
#include <cstdlib>
using namespace std;

const int N = 100000;           // 模拟次数
int crit_rate;                  // 暴击率*1000, 请输入小数或者百分数(不含百分号)
double crit_dmg;                // 暴击伤害(转化为小数), 请输入小数或者百分数(不含百分号)
double confident_rate = 0.95;   // 保证的概率(即p0)
double bonus_rate = 1.0;        // 为方便将双爆和倍率之外的区间设为了1000, 如果有真实伤害计算需要可以另填

// 倍率设定及演示
double base[] = {2489,4421,1649,1719,1044,1044,2070,4175,1632,1632,3628,1649,1719,1044,1044,2070,28009};
// double base[] = {826,2426,826,2426,826,2426,826,2426,826,2426,826,2426,826,2426,826,2426};
// double base[] = {636,636,1220,1586,828,828,1889,636,636,1220,1586,828,828,1889,636,636,1220,1586,828,828,1889};
// double base[] = {1370,1670,2080,2130,2130,2130,2130,2130,2130,2130,2130,2130,2130};
struct trate{
    int times;
    double dmg;
    trate(int times, double dmg) : times(times), dmg(dmg) {}
};
vector<double> res;
vector<trate> addres;

bool equals(double a, double b)
{
    return abs(a-b) < a * 1e-6;
}
int main()
{
    int B = sizeof(base) / sizeof(double);
    srand(time(0));
    double CD, CR;
    cin >> CR >> CD;
    if(CD < 0 || CR < 0)
    {
        printf("Invalid crit rate and crit dmg");
        return 0;
    }
    if(CR < 1) 
        crit_rate = round(CR * 1000);
    else 
        crit_rate = round(CR * 10);

    if(CD < 10)
        crit_dmg = CD;
    else
        crit_dmg = CD / 100;

    for(int i = 0;i < N;i++)
    {
        double tot_dmg = 0;
        for(int j = 0;j < B;j++)
            if(rand() % 1000 < crit_rate)
                tot_dmg += base[j] * bonus_rate * (1 + crit_dmg);
            else tot_dmg += base[j] * bonus_rate;
        res.push_back(tot_dmg);
    }
    sort(res.begin(), res.end());

    // 输出1%~99%
    for(int i = 1;i <= 99;i++)
        printf("%d%% : %g\n", i, res.at(i * N / 100));

    // 输出极限值
    // for(int i = 94 * N / 100;i < N;i++)
    // {
    //     if(!equals(res.at(i), res.at(i - 1)))
    //         addres.push_back(trate(ceil(log(1.0 - confident_rate) / log((i+0.0) / N)), res.at(i)));
    // }
    // for(int i = 0;i < addres.size();i++)
    // {
    //     if(i < addres.size() - 1 && addres.at(i).times == addres.at(i + 1).times)
    //         continue;
    //     printf("%d : %g\n", addres.at(i).times, addres.at(i).dmg);
    // }

    // 输出期望伤害
    // double expect_dmg = 0;
    // for(int i = 0;i < B;i++)
    //     expect_dmg += base[i] * bonus_rate * (1 + crit_dmg * crit_rate / 1000.0);
    // printf("expect : %g\n", expect_dmg);

    // 输出理论最高伤害
    double best_dmg = 0;
    for(int i = 0;i < B;i++)
        best_dmg += base[i] * bonus_rate * (1 + crit_dmg);
    printf("best : %g", best_dmg);
    
    return 0;
}